﻿using Moq;
using NUnit.Framework;
using System.Collections.Generic;
using System.Threading.Tasks;
using TabbedTemplate.Models;
using TabbedTemplate.Services;
using TabbedTemplate.ViewModels;

namespace UnitTest.ViewModels
{
    public class TestCityLocationsViewModel
    {
        [Test]
        public async Task TestPageAppearingCommand1()
        {
            var punchNavigationServiceMock = new Mock<IPunchNavigationService>();
            var mockPunchNavigationService = punchNavigationServiceMock.Object;

            var preferenceStorageMock = new Mock<IPreferenceStorage>();
            preferenceStorageMock.Setup(p => p.Get("CurrentCity", "北京市"))
                .Returns("北京市");
            preferenceStorageMock.Setup(p => p.Get("His1", "上海市"))
                .Returns("上海市");
            preferenceStorageMock.Setup(p => p.Get("His2", "重庆市"))
                .Returns("重庆市");
            var mockPreferenceStorage = preferenceStorageMock.Object;

            var cityLocationsServiceMock = new Mock<ICityLocationsService>();
            cityLocationsServiceMock.Setup(p => p.CityListInitilized())
                .Returns(true);
            var mockCityLocationsService = cityLocationsServiceMock.Object;

            var cityLocationsViewModel = new CityLocationsViewModel(mockPunchNavigationService,
                mockCityLocationsService, mockPreferenceStorage);

            var statusList = new List<string>();
            cityLocationsViewModel.PropertyChanged += (sender, args) =>
            {
                if (args.PropertyName == nameof(CityLocationsViewModel.Status))
                {
                    statusList.Add(cityLocationsViewModel.Status);
                }
            };

            var Cities = new List<City>();
            for (int i = 1; i < 10; i++)
            {
                Cities.Add(new City
                {
                    CityName = ""
                });
            }

            cityLocationsServiceMock.Setup(p =>
                p.GetCityListAsync(cityLocationsViewModel.Cities.Count, StoreService.PageSize)).ReturnsAsync(Cities);

            await cityLocationsViewModel.PageAppearingCommandFunction();
            Assert.AreEqual(IndexPageViewModel.NoMoreResult, statusList[0]);


        }
        [Test]
        public async Task TestPageAppearingCommand2()
        {
            var punchNavigationServiceMock = new Mock<IPunchNavigationService>();
            var mockPunchNavigationService = punchNavigationServiceMock.Object;

            var preferenceStorageMock = new Mock<IPreferenceStorage>();
            var mockPreferenceStorage = preferenceStorageMock.Object;

            var cityLocationsServiceMock = new Mock<ICityLocationsService>();
            var mockCityLocationsService = cityLocationsServiceMock.Object;

            var cityLocationsViewModel = new CityLocationsViewModel(mockPunchNavigationService,
                mockCityLocationsService, mockPreferenceStorage);

            var statusList = new List<string>();
            cityLocationsViewModel.PropertyChanged += (sender, args) =>
            {
                if (args.PropertyName == nameof(CityLocationsViewModel.Status))
                {
                    statusList.Add(cityLocationsViewModel.Status);
                }
            };

            var Cities = new List<City>();
            for (int i = 1; i < 10; i++)
            {
                Cities.Add(new City
                {
                    CityName = ""
                });
            }

            cityLocationsServiceMock.Setup(p =>
                p.GetCityListAsync(cityLocationsViewModel.Cities.Count, StoreService.PageSize)).ReturnsAsync(new List<City>());
            await cityLocationsViewModel.PageAppearingCommandFunction();
            Assert.AreEqual(IndexPageViewModel.NoResult, statusList[0]);
        }
        [Test]
        public async Task TestPageAppearingCommand3()
        {
            var punchNavigationServiceMock = new Mock<IPunchNavigationService>();
            var mockPunchNavigationService = punchNavigationServiceMock.Object;

            var preferenceStorageMock = new Mock<IPreferenceStorage>();
            var mockPreferenceStorage = preferenceStorageMock.Object;

            var cityLocationsServiceMock = new Mock<ICityLocationsService>();
            var mockCityLocationsService = cityLocationsServiceMock.Object;

            var cityLocationsViewModel = new CityLocationsViewModel(mockPunchNavigationService,
                mockCityLocationsService, mockPreferenceStorage);

            var statusList = new List<string>();
            cityLocationsViewModel.PropertyChanged += (sender, args) =>
            {
                if (args.PropertyName == nameof(CityLocationsViewModel.Status))
                {
                    statusList.Add(cityLocationsViewModel.Status);
                }
            };

            var Cities = new List<City>();
            for (int i = 1; i < 13; i++)
            {
                Cities.Add(new City
                {
                    CityName = ""
                });
            }

            cityLocationsServiceMock.Setup(p =>
                p.GetCityListAsync(cityLocationsViewModel.Cities.Count, StoreService.PageSize)).ReturnsAsync(Cities);
            await cityLocationsViewModel.PageAppearingCommandFunction();
            Assert.AreEqual("", statusList[0]);
        }

        [Test]
        public async Task TestCityTappedCommand()
        {
            var punchNavigationServiceMock = new Mock<IPunchNavigationService>();
            var mockPunchNavigationService = punchNavigationServiceMock.Object;
            var preferenceStorageMock = new Mock<IPreferenceStorage>();
            var mockPreferenceStorage = preferenceStorageMock.Object;
            var cityLocationsViewModel = new CityLocationsViewModel(mockPunchNavigationService,
                null, mockPreferenceStorage);
            var city = "";
            await cityLocationsViewModel.CityTappedCommandFunction(city);
            punchNavigationServiceMock.Verify(p => p.NavigateBackAsync(
                ContentNavigationConstant.NewIndexPage, city), Times.Once);
        }

        [Test]
        public async Task TestSpecialLocationCommandEqualsSpecialLocation()
        {
            string specialLocation = "重庆市";

            var preferenceStorageMock = new Mock<IPreferenceStorage>();
            preferenceStorageMock.Setup(p => p.Get("CurrentCity", "无"))
                .Returns(specialLocation);
            preferenceStorageMock.Setup(p => p.Get("currentLocationLatitude",
                double.MinValue)).Returns(1234);
            preferenceStorageMock.Setup(p => p.Get("currentLocationLongitude",
                double.MinValue)).Returns(12345);

            var mockPreferenceStorage = preferenceStorageMock.Object;

            var punchNavigationServiceMock =
                new Mock<IPunchNavigationService>();
            var mockPunchNavigationService = punchNavigationServiceMock.Object;

            var cityLocationsViewModel =
                new CityLocationsViewModel(mockPunchNavigationService, null,
                    mockPreferenceStorage);
            await cityLocationsViewModel.SpecialLocationCommandFunction(specialLocation);

            preferenceStorageMock.Verify(p => p.Get("currentLocationLatitude",
                double.MinValue), Times.Once);
            preferenceStorageMock.Verify(p => p.Get("currentLocationLongitude",
                double.MinValue), Times.Once);

            punchNavigationServiceMock.Verify(p => p.NavigateBackAsync(ContentNavigationConstant.NewIndexPage, specialLocation), Times.Once);

        }

        [Test]
        public async Task TestSpecialLocationCommandNotEqualsSpecialLocation()
        {
            string specialLocation = "重庆市";

            var preferenceStorageMock = new Mock<IPreferenceStorage>();
            preferenceStorageMock.Setup(p => p.Get("CurrentCity", "无"))
                .Returns("北京市");
            preferenceStorageMock.Setup(p => p.Get("currentLocationLatitude",
                double.MinValue)).Returns(1234);
            preferenceStorageMock.Setup(p => p.Get("currentLocationLongitude",
                double.MinValue)).Returns(12345);

            var mockPreferenceStorage = preferenceStorageMock.Object;

            var punchNavigationServiceMock =
                new Mock<IPunchNavigationService>();
            var mockPunchNavigationService = punchNavigationServiceMock.Object;

            var cityLocationsViewModel =
                new CityLocationsViewModel(mockPunchNavigationService, null,
                    mockPreferenceStorage);
            await cityLocationsViewModel.SpecialLocationCommandFunction(specialLocation);

            preferenceStorageMock.Verify(p => p.Get("currentLocationLatitude",
                double.MinValue), Times.Never);
            preferenceStorageMock.Verify(p => p.Get("currentLocationLongitude",
                double.MinValue), Times.Never);

            punchNavigationServiceMock.Verify(p => p.NavigateBackAsync(ContentNavigationConstant.NewIndexPage, specialLocation), Times.Once);

        }
    }
}
